#include <stdlib.h>
#include <stdio.h>
#include "image.h"

/* Fonctions */

Storage* checkStorage(Storage* storage){
	if(storage == NULL){
		storage = (Storage* )malloc(sizeof(Storage)*1);
		if(storage == NULL){
			printf("Erreur d'allocation mémoire");
		}
		else{
			storage->capacite = 20;
			storage->lastKey = 0;
			storage->album = (Image* )malloc(storage->capacite*sizeof(Image));
			if(storage->album == NULL){
				printf("Erreur d'allocation mémoire");
			}
			storage->album->type = NULL;
			storage->album->nbColumns = 0;
			storage->album->nbLines = 0;
			
			storage->album->pixels = NULL; 
			return storage;
		}
	}
	else if(storage->album[storage->capacite-1].pixels != NULL){
		storage->capacite *= 2;
		// storage->album = (Image* )realloc(storage->album, storage->capacite*sizeof(Image)); //PUTAIN DE REALLOC AVEC OFFSET, il ne realloc pas dans le bonne ordre !
		// 2 jours pour trouver ce bug qui vient de realloc et non de notre code...
		return storage;
	}
	return storage;
}

Storage* stockImg(Image* data, Storage* storage){
	int i = 0;
	
	if(storage != NULL){
		storage->lastKey++;
	}
	storage = checkStorage(storage);
	storage->album[storage->lastKey].type = data->type;
	storage->album[storage->lastKey].nbColumns = data->nbColumns;
	storage->album[storage->lastKey].nbLines = data->nbLines;
	storage->album[storage->lastKey].maxValueColor = data->maxValueColor;
	storage->album[storage->lastKey].pixels = data->pixels;
	//printf("Tout s'est REbien REpassé ! type : %s - %d - %d - %d - %d\n", storage->album[storage->lastKey].type, storage->album[storage->lastKey].nbColumns, storage->album[storage->lastKey].nbLines, storage->album[storage->lastKey].maxValueColor, storage->album[storage->lastKey].pixels); //test
	return storage;
}

Storage* scanImg(char* img, Storage* storage){
	FILE* image = fopen(img, "rb");
	Image* data = NULL;
	char tmp;

	if(image == NULL){ // vérification que img est bien au format ppm et que le fichier existe.
		printf("L'ouverture du fichier a échoué ou n'existe pas.\n");
		exit(1);
	}
	else{
		data = (Image* )malloc(sizeof(Image)*1);// malloc la zone mémoire necessaire pour recevoir une structure image.
		if(data == NULL){ //Gestion des erreurs eventuelles pour le malloc
			printf("Erreur d'allocation mémoire\n");
			exit(1);
		}
		data->type = (unsigned char* )malloc(sizeof(unsigned char)*2);// malloc la zone mémoire necessaire
		if(data->type == NULL){ //Gestion des erreurs eventuelles pour le malloc
			printf("Erreur d'allocation mémoire\n");
			exit(1);
		}
		data->nbColumns = 0;
		data->nbLines = 0;
		data->maxValueColor = 0;
		data->pixels = NULL;

		// fscanf(image, "%c%c", &(data->type[0]), &(data->type[1]));//Ajouter un \0 en type[2] ?
		fread(data->type, (sizeof(unsigned char)*1), 2, image); //récupère le type d'image ppm == P6
		if(data->type[0] == 'P' && (data->type[1]-'0') == 6){
			fread(&tmp,1,1,image);
			//Permet de sauter tout les espaces, sauts de lignes et commentaires.
			while(tmp == ' ' || tmp == '\n' || tmp == '#'){
				if(tmp == '#'){
					while (tmp != '\n'){
						fread(&tmp,1,1,image);
					}
				}
				fread(&tmp,1,1,image);
			}
			//récupère la hauteur de l'image
			// fscanf(image, "%d", &(data->nbColumns));
			while ((tmp >= '0') && (tmp <= '9')){
				data->nbColumns *= 10;
				data->nbColumns += (tmp - '0');
				fread(&tmp,1,1,image);
			}
			//Permet de sauter tout les espaces, sauts de lignes et commentaires.
			while(tmp == ' ' || tmp == '\n' || tmp == '#'){
				if(tmp == '#'){
					while (tmp != '\n'){
						fread(&tmp,1,1,image);
					}
				}
				fread(&tmp,1,1,image);
			}
			//récupère la largeur de l'image
			// fscanf(image, "%d", &(data->nbLines));
			while ((tmp >= '0') && (tmp <= '9')){
				data->nbLines *= 10;
				data->nbLines += (tmp - '0');
				fread(&tmp,1,1,image);
			}
			//Permet de sauter tout les espaces, sauts de lignes et commentaires.
			while(tmp == ' ' || tmp == '\n' || tmp == '#'){
				if(tmp == '#'){
					while (tmp != '\n'){
						fread(&tmp,1,1,image);
					}
				}
				fread(&tmp,1,1,image);
			}
			//récupère la valeur maximum du codage couleur de l'image
			// fscanf(image, "%d", &(data->maxValueColor));
			while ((tmp >= '0') && (tmp <= '9')){
				data->maxValueColor *= 10;
				data->maxValueColor += (tmp - '0');
				fread(&tmp,1,1,image); //Le dernier saut de ligne est pris en compte ici !
			}

			data->pixels = (unsigned char* )malloc(sizeof(unsigned char)*(data->nbColumns*data->nbLines*3));
			if(data->pixels == NULL){ //Gestion des erreurs eventuelles pour le malloc
				printf("Erreur d'allocation mémoire\n");
				exit(1);
			}
			fread(data->pixels, sizeof(unsigned char), (data->nbColumns*data->nbLines*3), image); //récupère les données binaires qui font l'image
			fflush(image);
			fclose(image);
			// printf("Tout s'est bien passé ! type : %s - %d - %d - %d - %d\n", data->type, data->nbColumns, data->nbLines, data->maxValueColor, data->pixels); //test
			storage = stockImg(data, storage); // stock l'image dans l'album et retourne l'adresse de l'image courante
		}
		else{
			printf("Ceci n'est pas une image ppm de type P6\n");
		}
	}
	return storage;
}

unsigned char* inverseImg(Image* img){
	unsigned int i,j,k,l,m;

	unsigned char* temp = (unsigned char*) malloc((img->nbColumns)*(img->nbLines)*3*sizeof(unsigned char));
	if (temp == NULL) {
		printf("Erreur d'allocation dans mémoire\n");
		exit(1);
	}
	// Pour chaque ligne
	k = 0;
	for(i = 0;i<(img->nbLines);i++) {
		for(j = 0;j<(img->nbColumns*3);j++) {
			temp[k++] = (unsigned char)(int)(img->pixels[i*img->nbColumns*3+j]);
		}
	}

	//inverse tabRVB pour afficher à l'endroit
	unsigned char* tabRVB = (unsigned char*) malloc((img->nbColumns)*(img->nbLines)*3*sizeof(unsigned char));
	if (tabRVB == NULL) {
		printf("Erreur d'allocation dans mémoire\n");
		exit(1);
	}

	m = 0;
	for(i=(img->nbLines); i>0; i--){
		for(j=0; j<(img->nbColumns*3); j++){
			tabRVB[m++] = temp[i*img->nbColumns*3+j];
		}
	}
	free(temp);
	temp = NULL;
	
	return tabRVB;
}

Image* background(int w_im, int h_im){
	unsigned int i,j,k;
	Image* img = NULL;
	img = (Image*)malloc(sizeof(Image));
	if(img == NULL){
		printf("Erreur d'allocation mémoire\n");
		exit(1); //Faire une recherche ou poser la question à un prof pour comment gérer le retour d'erreurs.
	}
	else{
		img->type = (unsigned char*)malloc(sizeof(unsigned char));
		if(img->type == NULL){
			printf("Erreur d'allocation mémoire\n");
			exit(1); //Faire une recherche ou poser la question à un prof pour comment gérer le retour d'erreurs.
		}
		img->type[0] = 'P';
		img->type[1] = '6';
		img->nbColumns = w_im;
		img->nbLines = h_im;
		img->maxValueColor = 255;
		img->pixels = (unsigned char*)malloc(w_im*h_im*3*sizeof(unsigned char));
		if (img->pixels == NULL) {
			printf("Erreur d'allocation dans background\n");
			exit(1);
		}
		// Pour chaque ligne
		k = 0;
		for(i = 0;i<(h_im);i++) {
			for(j = 0;j<(w_im);j++) {
				img->pixels[k++] = (unsigned char)(int)255;
				img->pixels[k++] = (unsigned char)(int)255;
				img->pixels[k++] = (unsigned char)(int)255;
			}
		}
		return img;
	}
}

int writeppm(Image* image, char *nom){
    FILE* fdat;
    
    fdat = fopen(nom,"w");
    if (fdat == NULL){
	    printf("Probleme en ecriture de %s ! \n",nom);
	    return 1;
    }
    else{
	    fprintf(fdat,"P6\n#Imagimp - 2012 - Angeline & Adrien\n%d %d\n%d\n",image->nbColumns,image->nbLines,image->maxValueColor);
	    fwrite(image->pixels, sizeof(unsigned char), image->nbColumns*image->nbLines*3, fdat);
	    fclose(fdat);
	    printf("Votre image a bien ete enregistree.\n");
	    return 0;
	}
    return 1;
}